﻿using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using AutoMapper;
using Demo.DtoParameters;
using Demo.Entities;
using Demo.Models.Dto;
using Demo.Services;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.JsonPatch;
using Microsoft.AspNetCore.Mvc;

namespace Demo.Controllers
{
    [ApiController]
    public class EmployeesController : ControllerBase
    {
        private readonly IEmployeeService _employeeService;
        private readonly IMapper _mapper;
        private readonly ICompanyService _companyService;

        public EmployeesController(IEmployeeService _employeeService, IMapper _mapper, ICompanyService _companyService)
        {
            this._employeeService = _employeeService ?? throw new ArgumentNullException(nameof(_employeeService));
            this._mapper = _mapper ?? throw new ArgumentNullException(nameof(_mapper));
            this._companyService = _companyService ?? throw new ArgumentNullException(nameof(_companyService));
        }

        [HttpGet("api/companies/{companyId}/employees")]
        public async Task<ActionResult<IEnumerable<EmployeeDto>>> GetEmployeesForCompany(Guid companyId,
            EmployeeDtoParameters parameters)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound();
            }

            var employees = await _employeeService.GetEmployeesAsync(companyId, parameters);

            var employeDtos = _mapper.Map<IEnumerable<EmployeeDto>>(employees);

            return Ok(employeDtos);
        }

        [HttpGet("api/companies/{companyId}/employees/{employeeId}", Name = nameof(GetEmployeesForCompany))]
        public async Task<ActionResult<EmployeeDto>> GetEmployeesForCompany(Guid companyId, Guid employeeId)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound();
            }

            var employee = await _employeeService.GetEmployeeAsync(companyId, employeeId);
            if (employee == null)
            {
                return NotFound();
            }

            return Ok(_mapper.Map<EmployeeDto>(employee));
        }

        [HttpPost("api/companies/{companyId}/employees", Name = nameof(CreateEmployee))]
        public async Task<ActionResult<EmployeeDto>> CreateEmployee(Guid companyId, EmployeeAddDto employeeAddDto)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound("未找到指定公司");
            }

            var employee = _mapper.Map<Employee>(employeeAddDto);

            _employeeService.AddEmployee(companyId, employee);
            var employeeDto = _mapper.Map<EmployeeDto>(employee);

            return CreatedAtRoute(nameof(GetEmployeesForCompany), new {companyId, employeeId = employeeDto.Id},
                employeeDto);
        }

        [HttpPut("api/companies/{companyId}/employees/{employeeId}")]
        public async Task<IActionResult> UpdateEmployeeFromCompany(Guid companyId, Guid employeeId,
            EmployeeUpdateDto employeeUpdateDto)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound("对应公司未找到");
            }

            var employeeEntity = await _employeeService.GetEmployeeAsync(companyId, employeeId);

            if (employeeEntity == null)
            {
                var employeeAddDto = _mapper.Map<Employee>(employeeUpdateDto);
                employeeAddDto.Id = employeeId;
                _employeeService.AddEmployee(companyId, employeeAddDto);
                var employeeDto = _mapper.Map<EmployeeDto>(employeeAddDto);

                return CreatedAtRoute(nameof(GetEmployeesForCompany), new {companyId, employeeId},
                    employeeDto);
            }

            _mapper.Map(employeeUpdateDto, employeeEntity);

            _employeeService.UpdateEmployee(employeeEntity);
            return NoContent();
        }

        [HttpPatch("api/companies/{companyId}/employees/{employeeId}")]
        public async Task<IActionResult> PartiallyUpdateEmployee(Guid companyId, Guid employeeId,
            JsonPatchDocument<EmployeeUpdateDto> patchDocument)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound("对应公司未找到");
            }

            var employeeEntity = await _employeeService.GetEmployeeAsync(companyId, employeeId);

            if (employeeEntity == null)
            {
                return NotFound("对应员工未找到");
            }

            var employeeDto = _mapper.Map<EmployeeUpdateDto>(employeeEntity);

            //校验失败返回错误
            if (!TryValidateModel(employeeDto))
            {
                return ValidationProblem(
                    "请看详细信息",
                    Response.HttpContext.Request.Path,
                    StatusCodes.Status422UnprocessableEntity,
                    "有错误!", "https://www.baidu.com",
                    ModelState
                );
            }

            patchDocument.ApplyTo(employeeDto, ModelState);

            _mapper.Map(employeeDto, employeeEntity);

            _employeeService.UpdateEmployee(employeeEntity);

            return NoContent();
        }

        [HttpDelete("api/companies/{companyId}/employees/{employeeId}")]
        public async Task<IActionResult> DeleteEmployee(Guid companyId, Guid employeeId)
        {
            if (!await _companyService.CompanyExistsAsync(companyId))
            {
                return NotFound("对应公司未找到");
            }

            var employeeEntity = await _employeeService.GetEmployeeAsync(companyId, employeeId);

            if (employeeEntity == null)
            {
                return NotFound("对应员工未找到");
            }

            _employeeService.DeleteEmployee(employeeEntity);
            return NoContent();
        }
    }
}